#include "./BSP/MPU6050/MPU6050.h"

uint8_t mpu6050_write(uint8_t addr,uint8_t reg,uint8_t len,uint8_t *data)
{
    unsigned char i;
	addr = addr<<1;
	MPU6050_IIC_Start();						//I2C起始
	MPU6050_IIC_Send_Byte(addr);			//发送从机地址，读写位为0，表示即将写入
	MPU6050_IIC_Send_Byte(reg);			//发送寄存器地址
	for (i = 0; i< len;i++)
		MPU6050_IIC_Send_Byte(*data++);
	MPU6050_IIC_Stop();						//I2C终止

	return 0;									//返回0，表示成功
}

uint8_t mpu6050_read(uint8_t addr,uint8_t reg,uint8_t len,uint8_t *data)
{
	unsigned char i;
	addr = addr<<1;
	MPU6050_IIC_Start();						//I2C起始
	MPU6050_IIC_Send_Byte(addr);			//发送从机地址，读写位为0，表示即将写入
	MPU6050_IIC_Send_Byte(reg);			//发送寄存器地址

	MPU6050_IIC_Start();						//I2C重复起始
	MPU6050_IIC_Send_Byte(addr+1);	//发送从机地址，读写位为1，表示即将读取
	for (i = 0; i< len-1;i++)
		*data++ = MPU6050_IIC_Read_Byte(0);			//接收指定寄存器的数据
	*data=MPU6050_IIC_Read_Byte(1);
	MPU6050_IIC_Stop();						//I2C终止
	return 0;									//返回0，表示成功
}

/**
  * 函    数：MPU6050写寄存器
  * 参    数：RegAddress 寄存器地址，范围：参考MPU6050手册的寄存器描述
  * 参    数：Data 要写入寄存器的数据，范围：0x00~0xFF
  * 返 回 值：无
  */
void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)
{
	mpu6050_write(MPU_ADDR,RegAddress,1,&Data);
}

/**
  * 函    数：MPU6050读寄存器
  * 参    数：RegAddress 寄存器地址，范围：参考MPU6050手册的寄存器描述
  * 返 回 值：读取寄存器的数据，范围：0x00~0xFF
  */
uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{
	uint8_t Data;
	mpu6050_read(MPU_ADDR,RegAddress,1,&Data);
	return Data;
}
//设置MPU6050陀螺仪传感器满量程范围
//fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
//返回值:0,设置成功
//    其他,设置失败 
uint8_t MPU_Set_Gyro_Fsr(uint8_t fsr)
{
	MPU6050_WriteReg(GYRO_CONFIG,fsr<<3);//设置陀螺仪满量程范围  
	return 0;
}
//设置MPU6050加速度传感器满量程范围
//fsr:0,±2g;1,±4g;2,±8g;3,±16g
//返回值:0,设置成功
//    其他,设置失败 
uint8_t MPU_Set_Accel_Fsr(uint8_t fsr)
{
	MPU6050_WriteReg(ACCEL_CONFIG,fsr<<3);//设置加速度传感器满量程范围  
	return 0;
}

//设置MPU6050的数字低通滤波器
//lpf:数字低通滤波频率(Hz)
//返回值:0,设置成功
//    其他,设置失败 
uint8_t MPU_Set_LPF(uint16_t lpf)
{
	uint8_t data=0;
	if(lpf>=188)data=1;
	else if (lpf>=98) data=2;
	else if (lpf>=42) data=3;
	else if (lpf>=20) data=4;
	else if (lpf>=10) data=5;
	else data=6;
	MPU6050_WriteReg(MPU_CFG_REG,data);
	return 0;
}

//设置MPU6050的采样率(假定Fs=1KHz)
//rate:4~1000(Hz)
//返回值:0,设置成功
//    其他,设置失败 
uint8_t MPU_Set_Rate(uint16_t rate)
{
	uint8_t data;
	if(rate>1000) rate=1000;
	if(rate<4) rate=4;
	data=1000/rate-1;
	MPU6050_WriteReg(MPU_SAMPLE_RATE_REG,data);
	return MPU_Set_LPF(rate/2);
}

//----------------------------------------------------------------------
/**
  * 函    数：MPU6050初始化
  * 参    数：无
  * 返 回 值：无
  */
void MPU6050_Init(void)
{
	uint8_t res;
	MPU6050_IIC_IO_Init();							//先初始化底层的I2C
	MPU6050_WriteReg(PWR_MGMT_1,0X80);	//复位MPU6050
    delay_ms(100);
	MPU6050_WriteReg(PWR_MGMT_1,0X00);	//唤醒MPU6050 
	MPU_Set_Gyro_Fsr(3);					//陀螺仪传感器,±2000dps
	MPU_Set_Accel_Fsr(3);					//加速度传感器,±2g
	MPU_Set_Rate(200);						//设置采样率50Hz
	MPU6050_WriteReg(MPU_INT_EN_REG,0X00);	//关闭所有中断
	MPU6050_WriteReg(MPU_USER_CTRL_REG,0X00);	//I2C主模式关闭
	MPU6050_WriteReg(MPU_FIFO_EN_REG,0X00);	//关闭FIFO
	MPU6050_WriteReg(MPU_INTBP_CFG_REG,0X80);	//INT引脚低电平有效
	res=MPU6050_ReadReg(MPU_DEVICE_ID_REG); 
	if(res==MPU_ADDR)//器件ID正确
	{
		MPU6050_WriteReg(PWR_MGMT_1,0X01);	//设置CLKSEL,PLL X轴为参考
		MPU6050_WriteReg(PWR_MGMT_2,0X00);	//加速度与陀螺仪都工作
		MPU_Set_Rate(100);						//设置采样率为50Hz
 	}
}

uint8_t MPU6050_GetID(void)
{
	return MPU6050_ReadReg(MPU_DEVICE_ID_REG);		//返回WHO_AM_I寄存器的值
}

//得到温度值
//返回值:温度值(扩大了100倍)
short MPU_Get_Temperature(void)
{
    uint8_t buf[2]; 
    short raw;
	float temp;
	mpu6050_read(MPU_ADDR,TEMP_OUT_H,2,buf); 
    raw=((uint16_t)buf[0]<<8)|buf[1];  
    temp=36.53+((double)raw)/340;  
    return temp*100;
}
//得到陀螺仪值(原始值)
//gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
//返回值:0,成功
//    其他,错误代码
void MPU_Get_Gyroscope(short *gx,short *gy,short *gz)
{
	uint8_t DataH, DataL;								//定义数据高8位和低8位的变量
	DataH = MPU6050_ReadReg(GYRO_XOUT_H	);		//读取陀螺仪X轴的高8位数据
	DataL = MPU6050_ReadReg(GYRO_XOUT_L	);		//读取陀螺仪X轴的低8位数据
	*gx = (DataH << 8) | DataL;						//数据拼接，通过输出参数返回
	
	DataH = MPU6050_ReadReg(GYRO_YOUT_H	);		//读取陀螺仪Y轴的高8位数据
	DataL = MPU6050_ReadReg(GYRO_YOUT_L	);		//读取陀螺仪Y轴的低8位数据
	*gy = (DataH << 8) | DataL;						//数据拼接，通过输出参数返回
	
	DataH = MPU6050_ReadReg(GYRO_ZOUT_H	);		//读取陀螺仪Z轴的高8位数据
	DataL = MPU6050_ReadReg(GYRO_ZOUT_L );		//读取陀螺仪Z轴的低8位数据
	*gz = (DataH << 8) | DataL;						//数据拼接，通过输出参数返回
}
//得到加速度值(原始值)
//gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
//返回值:0,成功
//    其他,错误代码
void MPU_Get_Accelerometer(short *ax,short *ay,short *az)
{
	uint8_t DataH, DataL;								//定义数据高8位和低8位的变量
	
	DataH = MPU6050_ReadReg(ACCEL_XOUT_H);		//读取加速度计X轴的高8位数据
	DataL = MPU6050_ReadReg(ACCEL_XOUT_L);		//读取加速度计X轴的低8位数据
	*ax = (DataH << 8) | DataL;						//数据拼接，通过输出参数返回
	
	DataH = MPU6050_ReadReg(ACCEL_YOUT_H);		//读取加速度计Y轴的高8位数据
	DataL = MPU6050_ReadReg(ACCEL_YOUT_L);		//读取加速度计Y轴的低8位数据
	*ay = (DataH << 8) | DataL;						//数据拼接，通过输出参数返回
	
	DataH = MPU6050_ReadReg(ACCEL_ZOUT_H);		//读取加速度计Z轴的高8位数据
	DataL = MPU6050_ReadReg(ACCEL_ZOUT_L);		//读取加速度计Z轴的低8位数据
	*az = (DataH << 8) | DataL;						//数据拼接，通过输出参数返回
}
